package org.jsola.hr.service.impl;

import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrLogKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpSocChangesDAO;
import org.jsola.hr.dto.AttendanceMonthlyAddDTO;
import org.jsola.hr.dto.AttendanceMonthlyUpdateDTO;
import org.jsola.hr.dto.EmpSocChangesAddDTO;
import org.jsola.hr.dto.EmpSocChangesUpdateDTO;
import org.jsola.hr.entity.EmpSocChangesDO;
import org.jsola.hr.query.EmpSocChangesQuery;
import org.jsola.hr.service.IEmpSocChangesService;
import org.jsola.hr.vo.EmpSocChangesListVO;
import org.jsola.hr.vo.EmpSocChangesVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * @author zhr
 */
@Service("hrEmpSocChangesServiceImpl")
public class EmpSocChangesServiceImpl implements IEmpSocChangesService {

    @Autowired
    private IEmpSocChangesDAO empSocChangesDAO;


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpSocChangesVO save(EmpSocChangesAddDTO empSocChangesAddDTO, TokenUser tokenUser) {
        // 转DO
        EmpSocChangesDO empSocChangesDO = empSocChangesAddDTO.to(EmpSocChangesDO.class);
        // 保存
        empSocChangesDO = save(empSocChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empSocChangesDO.to(EmpSocChangesVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpSocChangesUpdateDTO empSocChangesUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpSocChangesDO empSocChangesDO = empSocChangesUpdateDTO.to(EmpSocChangesDO.class);
        HrLogKit.logForUpdate("更新员工社保相关信息", "empSocChanges", empSocChangesDO.getId(), tokenUser);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empSocChangesDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empSocChangesIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empSocChangesIds);
    }


    @Override
    public EmpSocChangesVO selectById(String empSocChangesId, String siteId) {
        EmpSocChangesDO empSocChangesDO = selectDOById(empSocChangesId, siteId);
        if (empSocChangesDO == null) {
            return null;
        }
        return empSocChangesDO.to(EmpSocChangesVO.class);
    }

    @Override
    public List<EmpSocChangesListVO> select(EmpSocChangesQuery empSocChangesQuery, String siteId) {
        List<EmpSocChangesDO> empSocChangesDOList = selectDO(empSocChangesQuery, siteId);
        if(CollectionUtils.isEmpty(empSocChangesDOList)) {
            return empSocChangesDOList == null ? null : new ArrayList<>();
        }
        return empSocChangesDOList.stream()
                .map(empSocChangesDO -> empSocChangesDO.to(EmpSocChangesListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpSocChangesQuery empSocChangesQuery, String siteId) {
        Example example = buildExample(empSocChangesQuery,siteId);
        return empSocChangesDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpSocChangesListVO> selectPage(EmpSocChangesQuery empSocChangesQuery, String siteId) {
        Example example = buildExample(empSocChangesQuery,siteId);
        Page<EmpSocChangesDO> page = empSocChangesDAO.selectPageByExample(example,
                empSocChangesQuery.getPageNo(),
                empSocChangesQuery.getPageSize());

        return page.to(EmpSocChangesListVO.class);
    }

    @Override
    public EmpSocChangesDO selectDOById(String empSocChangesId, String siteId) {
        return listById(empSocChangesId, siteId);
    }

    @Override
    public List<EmpSocChangesDO> selectDO(EmpSocChangesQuery empSocChangesQuery, String siteId) {
        Example example = buildExample(empSocChangesQuery,siteId);
        return empSocChangesDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example

     * @param empSocChangesQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(EmpSocChangesQuery empSocChangesQuery, String siteId) {
        Example example = new Example(EmpSocChangesDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empSocChangesQuery.getEmpId() != null) {
            example.and().andLike("empId", "%" + empSocChangesQuery.getEmpId() + "%");
        }
        if (empSocChangesQuery.getSocCity() != null) {
            example.and().andLike("socCity", "%" + empSocChangesQuery.getSocCity() + "%");
        }
        if (empSocChangesQuery.getSocType() != null) {
            example.and().andEqualTo("socType", empSocChangesQuery.getSocType());
        }
        if (empSocChangesQuery.getSocBasic() != null) {
            example.and().andEqualTo("socBasic", empSocChangesQuery.getSocBasic());
        }
        if (empSocChangesQuery.getSocPropCompany() != null) {
            example.and().andEqualTo("socPropCompany", empSocChangesQuery.getSocPropCompany());
        }
        if (empSocChangesQuery.getSocPropPerson() != null) {
            example.and().andEqualTo("socPropPerson", empSocChangesQuery.getSocPropPerson());
        }
        if (empSocChangesQuery.getSocAmountCompany() != null) {
            example.and().andEqualTo("socAmountCompany", empSocChangesQuery.getSocAmountCompany());
        }
        if (empSocChangesQuery.getSocAmountPerson() != null) {
            example.and().andEqualTo("socAmountPerson", empSocChangesQuery.getSocAmountPerson());
        }
        if (empSocChangesQuery.getSocRemark() != null) {
            example.and().andLike("socRemark", "%" + empSocChangesQuery.getSocRemark() + "%");
        }
        if (empSocChangesQuery.getSocMain() != null) {
            example.and().andEqualTo("socMain", empSocChangesQuery.getSocMain());
        }
        if (empSocChangesQuery.getCensusType() != null) {
            example.and().andEqualTo("censusType", empSocChangesQuery.getCensusType());
        }
        if (empSocChangesQuery.getWorkInjuryProp() != null) {
            example.and().andEqualTo("workInjuryProp", empSocChangesQuery.getWorkInjuryProp());
        }
        if (empSocChangesQuery.getPfCity() != null) {
            example.and().andLike("pfCity", "%" + empSocChangesQuery.getPfCity() + "%");
        }
        if (empSocChangesQuery.getPfBasic() != null) {
            example.and().andEqualTo("pfBasic", empSocChangesQuery.getPfBasic());
        }
        if (empSocChangesQuery.getPfPropCompany() != null) {
            example.and().andEqualTo("pfPropCompany", empSocChangesQuery.getPfPropCompany());
        }
        if (empSocChangesQuery.getPfPropPerson() != null) {
            example.and().andEqualTo("pfPropPerson", empSocChangesQuery.getPfPropPerson());
        }
        if (empSocChangesQuery.getPfAmountCompany() != null) {
            example.and().andEqualTo("pfAmountCompany", empSocChangesQuery.getPfAmountCompany());
        }
        if (empSocChangesQuery.getPfAmountPerson() != null) {
            example.and().andEqualTo("pfAmountPerson", empSocChangesQuery.getPfAmountPerson());
        }
        if (empSocChangesQuery.getPfTaxAmount() != null) {
            example.and().andEqualTo("pfTaxAmount", empSocChangesQuery.getPfTaxAmount());
        }
        if (empSocChangesQuery.getPfRemark() != null) {
            example.and().andLike("pfRemark", "%" + empSocChangesQuery.getPfRemark() + "%");
        }
        if (empSocChangesQuery.getPersonTaxProp() != null) {
            example.and().andEqualTo("personTaxProp", empSocChangesQuery.getPersonTaxProp());
        }
        if (empSocChangesQuery.getPersonTaxAmount() != null) {
            example.and().andEqualTo("personTaxAmount", empSocChangesQuery.getPersonTaxAmount());
        }
        if (empSocChangesQuery.getSocUnpayMonth() != null) {
            example.and().andEqualTo("socUnpayMonth", empSocChangesQuery.getSocUnpayMonth());
        }
        if (empSocChangesQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empSocChangesQuery.getCompanyId());
        }
        if (empSocChangesQuery.getPfUnpayMonth() != null) {
            example.and().andEqualTo("pfUnpayMonth", empSocChangesQuery.getPfUnpayMonth());
        }
        if (empSocChangesQuery.getSocPaybackMonth() != null) {
            example.and().andEqualTo("socPaybackMonth", empSocChangesQuery.getSocPaybackMonth());
        }
        if (empSocChangesQuery.getPfPaybackMonth() != null) {
            example.and().andEqualTo("pfPaybackMonth", empSocChangesQuery.getPfPaybackMonth());
        }
        if (empSocChangesQuery.getSocPaybackMonthAmount() != null) {
            example.and().andEqualTo("socPaybackMonthAmount", empSocChangesQuery.getSocPaybackMonthAmount());
        }
        if (empSocChangesQuery.getPfPaybackMonthAmount() != null) {
            example.and().andEqualTo("pfPaybackMonthAmount", empSocChangesQuery.getPfPaybackMonthAmount());
        }
        if (empSocChangesQuery.getSocPaybackMonthRemark() != null) {
            example.and().andLike("socPaybackMonthRemark", "%" + empSocChangesQuery.getSocPaybackMonthRemark() + "%");
        }
        if (empSocChangesQuery.getPfPaybackMonthRemark() != null) {
            example.and().andLike("pfPaybackMonthRemark", "%" + empSocChangesQuery.getPfPaybackMonthRemark() + "%");
        }
        if (empSocChangesQuery.getEffectiveStatus() != null) {
            example.and().andEqualTo("effectiveStatus", empSocChangesQuery.getEffectiveStatus());
        }
        if (empSocChangesQuery.getEffectiveDateStart() != null &&
                empSocChangesQuery.getEffectiveDateEnd() != null) {
            example.and().andBetween("effectiveDate", empSocChangesQuery.getEffectiveDateStart(),
                    empSocChangesQuery.getEffectiveDateEnd());
        }
        if (empSocChangesQuery.getGmtCreateStart() != null &&
                empSocChangesQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", empSocChangesQuery.getGmtCreateStart(),
                    empSocChangesQuery.getGmtCreateEnd());
        }
        if (empSocChangesQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + empSocChangesQuery.getCreateUserId() + "%");
        }
        if (empSocChangesQuery.getGmtModifiedStart() != null &&
                empSocChangesQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", empSocChangesQuery.getGmtModifiedStart(),
                    empSocChangesQuery.getGmtModifiedEnd());
        }
        if (empSocChangesQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + empSocChangesQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example,empSocChangesQuery.getOrders());
        return example;
    }

    @Override
    public EmpSocChangesDO getEmpSocBasicByEmpId(String empId, String siteId){
        return empSocChangesDAO.getEmpSocBasicByEmpId(empId, siteId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Boolean empSocPfPersonTaxDedCount(TokenUser tokenUser, AttendanceMonthlyAddDTO attendanceMonthlyAddDTO){
        //获取员工社保信息列表
        EmpSocChangesDO empSocChangesDO = new EmpSocChangesDO();
        empSocChangesDO.setValid(true);
        empSocChangesDO.setSiteId(tokenUser.getSiteId());
        empSocChangesDO.setEffectiveStatus(true);
        empSocChangesDO.setCompanyId(attendanceMonthlyAddDTO.getCompanyId());
        List<EmpSocChangesVO> empSocChangesVOList = empSocChangesDAO.selectSocChangesWithSalary(empSocChangesDO);
        List<AttendanceMonthlyUpdateDTO> attendanceMonthlyUpdateDTOList = new ArrayList<>();
        for (EmpSocChangesVO empSocChangesVO : empSocChangesVOList) {
            Integer socAmount = 0;
            Integer pfAmount = 0;
            Integer personTax = 0;
            //社保
            if(!empSocChangesVO.getSocUnpayMonth()){
                if(Objects.nonNull(empSocChangesVO.getSocAmountPerson())){
                    socAmount = empSocChangesVO.getSocAmountPerson();
                }else{
                    socAmount = new BigDecimal(empSocChangesVO.getSocBasic()).multiply(empSocChangesVO.getSocPropPerson()).intValue();
                }
            }
            //公积金
            if(!empSocChangesVO.getPfUnpayMonth()){
                if(Objects.nonNull(empSocChangesVO.getPfAmountPerson())){
                    pfAmount = empSocChangesVO.getPfAmountPerson();
                }else{
                    pfAmount = new BigDecimal(empSocChangesVO.getPfBasic()).multiply(empSocChangesVO.getPfPropPerson()).intValue();
                }
            }
            //个税
            if(Objects.nonNull(empSocChangesVO.getSalaryBasic()) && empSocChangesVO.getSalaryBasic() > HrConstants.SOC_BASIC_AMOUNT){
                if(Objects.nonNull(empSocChangesVO.getPersonTaxAmount())){
                    personTax = empSocChangesVO.getPersonTaxAmount();
                }else{
                    //TODO 个税计算不正确待修改：应纳税额=（工资薪金所得 -3500）x适用税率-速算扣除数
                    personTax = new BigDecimal(empSocChangesVO.getSalaryBasic()).multiply(empSocChangesVO.getPersonTaxProp()).intValue();
                }
            }
            //本月补缴社保
            if(empSocChangesVO.getSocPaybackMonth()){
                socAmount += (empSocChangesVO.getSocPaybackMonthAmount() == null ? 0 : empSocChangesVO.getSocPaybackMonthAmount());
            }
            //本月补缴公积金
            if(empSocChangesVO.getPfPaybackMonth()){
                pfAmount += (empSocChangesVO.getPfPaybackMonthAmount() == null ? 0 : empSocChangesVO.getPfPaybackMonthAmount());
            }

            AttendanceMonthlyUpdateDTO attendanceMonthlyUpdateDTO = new AttendanceMonthlyUpdateDTO();
            attendanceMonthlyUpdateDTO.setYear(attendanceMonthlyAddDTO.getYear());
            attendanceMonthlyUpdateDTO.setMonth(attendanceMonthlyAddDTO.getMonth());
            attendanceMonthlyUpdateDTO.setEmpId(empSocChangesVO.getEmpId());
            attendanceMonthlyUpdateDTO.setSocDed(socAmount);
            attendanceMonthlyUpdateDTO.setPfDed(pfAmount);
            attendanceMonthlyUpdateDTO.setPersonTaxDed(personTax);
            attendanceMonthlyUpdateDTOList.add(attendanceMonthlyUpdateDTO);
        }
        HrLogKit.logForUpdate("计算社保公积金个税并更新考勤月统计：" + attendanceMonthlyAddDTO.getYear() + "年" + attendanceMonthlyAddDTO.getMonth() + "月", "attendanceMonthly", "0", tokenUser);
        if(CollectionUtils.isEmpty(attendanceMonthlyUpdateDTOList)){
            HrLogKit.logSystem("员工考勤月统计列表为空", tokenUser);
        }else{
            empSocChangesDAO.updateAttendanceMonthlyList(attendanceMonthlyUpdateDTOList);
        }

        return true;
    }
}





